package com.springmq.mq.juc;

import lombok.Data;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.threads.ThreadPoolExecutor;

import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @ClassName : TestDemo01
 * @Author : lby
 * @Date: 2021/2/3 16:52
 * @Description : 生产者消费者关系
 * 当使用 wait 以及 notify方法时，必须使用synchronized
 *  使用lock锁替换synchronized
 *  await() 和
 */
public class Demo01 {
    public static void main(String[] args) {
        DemoTestLock demoTestLock = new DemoTestLock();
        ThreadPoolExecutor executor=new ThreadPoolExecutor(10,10,10, TimeUnit.MINUTES,new SynchronousQueue<Runnable>());
        ThreadPoolExecutor executor01=new ThreadPoolExecutor(10,10,10, TimeUnit.MINUTES,new SynchronousQueue<Runnable>());
        executor.execute(()->{
            for (int i = 0; i <5 ; i++) {
                demoTestLock.decrease();
            }

        });
        executor01.execute(()->{
            for (int i = 0; i <5 ; i++) {
                demoTestLock.increase();
            }
        });

    }
}

@Slf4j
@Data
class DemoTestLock{
    private int number=0;

    Lock lock=new ReentrantLock();
    Condition condition = lock.newCondition();
    /**
     *  为了实现指定线程执行的顺序，可以使用多个监视操作
     */
    Condition condition1 = lock.newCondition();
    Condition condition2= lock.newCondition();
    /**
     * 消费者去减
     */
    public  void decrease() {
        // 使用lock锁需要加锁解锁
        lock.lock();
        try {
            // 判断等待
            // 为了防止虚假唤醒问题，使用while循环
            while (number<=0){
                condition.await();
            }
            // 执行业务
            log.info("消费者执行方法:{}",number);
            number--;
            // 通知别人
            condition.signalAll();
            // 指定通知某一个线程
            condition1.signal();
        }catch (Exception e){
            e.printStackTrace();
        }
        finally {
            lock.unlock();
        }
    }
    /**
     * 生产者去加
     */
    public void increase() {
        // 判断等待
        // 使用lock锁需要加锁解锁
        lock.lock();
        try {
            // 为了防止虚假唤醒问题，使用while循环
            while (number>0){
                condition.await();
            }
            // 执行业务
            log.info("生产者执行方法:{}",number);
            number++;
            // 通知别人
            condition.signalAll();
        }catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}
